function push8(array,num) {
    array.push(num & 0xFF);
}

function push16(array,num) {
    array.push((num >> 8) & 0xFF,(num) & 0xFF  );
}

function pushStr(array,str) {
	var n = str.length;
	for (var i=0; i < n; i++) {
		array.push(str.charCodeAt(i));
	}
}

const PACKET_HEARTBEAT = 			1;
const PACKET_REENTER  =	 			100;
const PACKET_ROOM_REINIT  =	 		101;
const PACKET_LOGIN  = 				110;
const PACKET_LOGIN_ACK  = 			111;
const PACKET_SESSION_PARAM  = 		112;
const PACKET_LOGOUT  = 				113;
const PACKET_KICKOUT  = 			114;
const PACKET_ROOMCLEAR  = 			115;
const PACKET_ROOMHOT  = 			116;

const PACKET_SOMEBODY_IN  = 		120;
const PACKET_SOMEBODY_OUT  = 		121;
const PACKET_SOMEBODY_CHANGELEVEL = 122;
const PACKET_SOMEBODY_CHANGEAPPDATA=123;
const PACKET_SOMEBODY_CHATENABLE  = 124;

const PACKET_CHAT  = 				125;

const PACKET_TOKEN_NUMBER  =		140;
const PACKET_TOKEN_INFO  = 			141;
const PACKET_TOKEN_OP  = 			142;
const PACKET_TOKEN_OP_EX  =			143;
const PACKET_TOKEN_SETTING  = 		144;
const PACKET_TOKEN_TIMER  = 		145;	
export default class Xchatprotocol{
	constructor(arg) {
	  this.init()
	}
	init(){
		this.packet_fetch_state = 0
		this.packet_header = []
		this.packet_type = 0
		this.packet_para = 0
		this.packet_body = []
		this.packet_body_length = 0
		this.member_in_out_hint = 0
		this.Closed_By_Server = 0
		this.Closed_By_Client = false
		this.SessionID = 0
		this.logined = false
		this.passport = '0'
	}
	parse_header(){
		if (this.packet_header.length==4){
			this.packet_body_length = (this.packet_header[0]<<8)+this.packet_header[1];
			console.log('parse_header,packet_body_length,'+this.packet_body_length);
			this.packet_type = this.packet_header[2];
			this.packet_para = this.packet_header[3];
		}
		else{
			throw new("xchat_protocol packet header error.");
		}
	}
	process_packet(emitter,chatEvents){
		if (this.packet_type!=1){
			return;
		}
			
		if (this.packet_para == PACKET_HEARTBEAT){
			return;
		}
		
		var message_type;
		var packet_object;
		
		var temp = String.fromCharCode.apply(null,this.packet_body);
		
		try{
			packet_object = JSON.parse(temp);
		}
		catch (err){
			throw new Error("xchat_protocol packet body format error.");
			return;
		}
		
		
		if ('sessionid' in packet_object)
		packet_object['uid'] = packet_object['sessionid'];
		
		switch (this.packet_para){
			case PACKET_LOGIN_ACK:
				if (packet_object['loginack'] == 0){
					this.Closed_By_Server = 1;
				}
				else{
					this.logined = true;
					if (packet_object['passport']){
						this.passport = packet_object['passport'];
					}
				}
				message_type = 'MSG_LOGIN_ACK';
				break;
			case PACKET_REENTER:
				this.logined = false;
				this.Closed_By_Server = 1;
				message_type = 'MSG_REENTER';
				break;
			case PACKET_ROOM_REINIT:
				message_type = 'MSG_ROOM_REINIT';
				break;
			case PACKET_SESSION_PARAM:
				this.SessionID = packet_object['sessionid'];
				message_type = 'MSG_SESSION_PARAM';
				break;
			case PACKET_SOMEBODY_IN:
				packet_object['in_out_hint'] = this.member_in_out_hint;
				if (this.member_in_out_hint==0){
					if (this.SessionID == packet_object['sessionid']){
						this.member_in_out_hint = 1;
					}
				}
				message_type = 'MSG_SOMEBODY_IN';
				break;
			case PACKET_SOMEBODY_OUT:
				packet_object['in_out_hint'] = this.member_in_out_hint;
				message_type = 'MSG_SOMEBODY_OUT';
				break;
			case PACKET_SOMEBODY_CHANGELEVEL:
				if (this.SessionID == packet_object['sessionid']){
					packet_object['self'] = 1;
				}
				message_type = 'MSG_SOMEBODY_CHANGELEVEL';
				break;
			case PACKET_SOMEBODY_CHANGEAPPDATA:
				if (this.SessionID == packet_object['sessionid']){
					packet_object['self'] = 1;
				}
				message_type = 'MSG_SOMEBODY_CHANGEAPPDATA';
				break;
			case PACKET_SOMEBODY_CHATENABLE:
				if (this.SessionID == packet_object['sessionid']){
					packet_object['self'] = 1;
				}
				message_type = 'MSG_SOMEBODY_CHATENABLE';
				break;
			case PACKET_KICKOUT:
				if (this.SessionID == packet_object['sessionid']){
					packet_object['self'] = 1;
					this.Closed_By_Server = 1;
				}
				message_type = 'MSG_KICKOUT';
				break;
			case PACKET_ROOMCLEAR:
				this.Closed_By_Server = 1;
				message_type = 'MSG_ROOMCLEAR';
				break;
			case PACKET_ROOMHOT:
				message_type = 'MSG_ROOMHOT';
				break;
			case PACKET_CHAT:
				message_type = 'MSG_MESSAGE';
				break;
			case PACKET_TOKEN_SETTING:
				message_type = 'MSG_TOKEN_SETTING';
				break;
			case PACKET_TOKEN_TIMER:
				message_type = 'MSG_TOKEN_TIMER';
				break;	
			case PACKET_TOKEN_INFO:
				message_type = 'MSG_TOKEN_INFO';
				break;
			case PACKET_TOKEN_OP:
				message_type = 'MSG_TOKEN_REQUEST';
				if (packet_object['tokenop']==2){
					packet_object['type'] = 1;
				}
				else{
					packet_object['type'] = 0;
				}
				break;
			default :
				return;
		}
		emitter.trigger(chatEvents[message_type],packet_object)
	}
	Build_BA(para,Obj){
		if (Obj == null){
			var ba = [];
			push16(ba,0);
			push8(ba,1);
			push8(ba,para);
			return ba;
		}
		else{
			var s = JSON.stringify(Obj);
			var ba = [];
			push16(ba,s.length)
			push8(ba,1);
			push8(ba,para);
			pushStr(ba,s);
			return ba;
		}
	}
	packet_heartbeat(){
		return this.Build_BA(PACKET_HEARTBEAT,null)
	}
	packet_login(RoomID,UID,Level,appdata,token){
		var Obj = {};
		Obj['protocolversion'] = 257;//0x101;
		Obj['roomid'] = RoomID;
		Obj['roompara'] = 'RoomPara';
		Obj['gid'] = UID;
		Obj['level'] = Level;
		Obj['appdata'] = appdata;
		Obj['token'] = token;
		Obj['device'] = 1;

		if (this.passport !== '0'){
			Obj['passport'] = this.passport;
		}
		return this.Build_BA(PACKET_LOGIN,Obj);
	}
	packet_logout(){
		return this.Build_BA(PACKET_LOGOUT,null)
	}
}
